<template>
  <div class="base-list">
    <!-- 搜索区域 -->
    <div class="mb-4 flex items-center gap-4">
      <slot name="search">
        <!-- 默认搜索区域 -->
        <template v-for="(field, index) in searchFields" :key="index">
          <!-- 增加对 select 类型的支持 -->
          <template v-if="field.type === 'select'">
            <a-select
              v-model="searchForm[field.key]"
              :placeholder="field.placeholder"
              allow-clear
              class="!w-64"
              @change="handleInputChange"
            >
              <a-option v-for="option in field.options" :key="option.value" :value="option.value">
                {{ option.label }}
              </a-option>
            </a-select>
          </template>

          <!-- 默认为 input 类型 -->
          <template v-else>
            <a-input
              v-model="searchForm[field.key]"
              :placeholder="field.placeholder"
              allow-clear
              class="!w-64"
              @input="handleInputChange"
            >
              <template #prefix>
                <component :is="field.icon" />
              </template>
            </a-input>
          </template>
        </template>
      </slot>

      <!-- 默认按钮组 -->
      <BaseButton type="outline" @click="handleSearch">
        <template #icon>
          <BaseIcon name="icon-search" />
        </template>
        搜索
      </BaseButton>
      <BaseButton type="outline" status="warning" @click="handleReset">
        <template #icon>
          <BaseIcon name="icon-refresh" />
        </template>
        重置
      </BaseButton>
      <slot name="extra-buttons"></slot>
    </div>

    <!-- 表格区域 -->
    <div class="bg-white rounded-lg">
      <div class="flex items-center justify-between p-4 border-b border-gray-100">
        <div class="text-lg font-medium">{{ title }}</div>
        <slot name="toolbar">
          <template v-if="showAddButton">
            <template v-if="addPermission">
              <PermissionWrapper :code="addPermission">
                <BaseButton type="outline" status="success" @click="$emit('add')">
                  <template #icon><BaseIcon name="icon-plus" /></template>
                  {{ addButtonText }}
                </BaseButton>
              </PermissionWrapper>
            </template>
            <template v-else>
              <BaseButton type="outline" status="success" @click="$emit('add')">
                <template #icon><BaseIcon name="icon-plus" /></template>
                {{ addButtonText }}
              </BaseButton>
            </template>
          </template>
        </slot>
      </div>

      <a-table
        :data="data"
        :loading="loading"
        :row-key="rowKey"
        :pagination="{
          total: props.pagination?.total || 0,
          current: props.pagination?.current || 1,
          pageSize: props.pagination?.pageSize || 10,
          showTotal: true,
          showJumper: true,
          showPageSize: true,
        }"
        :tree-props="{
          children: childrenKey,
        }"
        class="base-list-table pb-3 px-3"
        @page-change="handlePageChange"
        @page-size-change="handlePageSizeChange"
      >
        <template #columns>
          <slot name="columns"></slot>
        </template>
      </a-table>
    </div>
  </div>
</template>

<script setup lang="ts" generic="T extends Record<string, any>">
import { ref, watch } from 'vue'
import type { BaseListProps, BasePaginationState, BaseSearchFormType } from '@/types/base-list'
import { debounce } from '@/utils/debounce'
import BaseIcon from './BaseIcon.vue'
import BaseButton from './BaseButton.vue'
import PermissionWrapper from './PermissionWrapper.vue'
import '@/assets/styles/components/base-list.css'

const props = withDefaults(
  defineProps<
    BaseListProps<T> & {
      pagination?: BasePaginationState
      debounceDelay?: number
      rowKey?: string
      childrenKey?: string
      addPermission?: string | string[]
    }
  >(),
  {
    title: '列表',
    loading: false,
    data: () => [],
    searchFields: () => [],
    showAddButton: true,
    addButtonText: '新增',
    debounceDelay: 500,
    rowKey: 'id',
    childrenKey: 'children',
    addPermission: undefined,
  },
)

const emit = defineEmits<{
  (e: 'search', form: BaseSearchFormType): void
  (e: 'reset'): void
  (e: 'update:pagination', pagination: BasePaginationState): void
  (e: 'add'): void
}>()

// 搜索表单
const searchForm = ref<BaseSearchFormType>({})

// 监听搜索字段变化，重置搜索表单
watch(
  () => props.searchFields,
  (fields) => {
    const newSearchForm = fields.reduce((acc, field) => {
      // 保留已有的搜索值
      acc[field.key] = searchForm.value[field.key] ?? ''
      return acc
    }, {} as BaseSearchFormType)
    searchForm.value = newSearchForm
  },
  { immediate: true },
)

/** 搜索 */
const handleSearch = () => {
  // 只发送搜索事件，让父组件决定如何处理分页和搜索
  emit('search', searchForm.value)
}

/** 处理输入变化 - 使用抖，延迟时间由props传入 */
const handleInputChange = debounce(() => {
  handleSearch()
}, props.debounceDelay)

/** 重置搜索 */
const handleReset = () => {
  // 重置搜索表单
  props.searchFields.forEach((field) => {
    searchForm.value[field.key] = ''
  })
  // 只发送重置事件，让父组件决定如何处理
  emit('reset')
}

/** 页码改变 */
const handlePageChange = (current: number) => {
  // 只更新分页信息，父组件会根据分页变化获取数据
  emit('update:pagination', {
    ...(props.pagination || { total: 0, pageSize: 10 }),
    current,
  })
}

/** 每页条数改变 */
const handlePageSizeChange = (pageSize: number) => {
  // 只更新分页信息，父组件会根据分页变化获取数据
  emit('update:pagination', {
    ...(props.pagination || { total: 0 }),
    pageSize,
    current: 1,
  })
}
</script>
